package com.controller;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import com.model.HeadImage;
import com.model.Tag;
import com.model.UploadImage;
import com.model.User;
import com.mortennobel.imagescaling.AdvancedResizeOp;
import com.mortennobel.imagescaling.ResampleOp;
import com.service.ArticleService;
import com.service.ImageStoreService;
import com.service.QuestionService;
import com.service.UserService;
import com.util.ImageUtils;

@Controller
@RequestMapping("/user")
public class UserController {

	@Autowired
    private UserService userService;
	
	@Autowired
    private ArticleService articleService;
	
	@Autowired
	private ImageStoreService imageStoreService;
	
	@Autowired
    private QuestionService questionService;
	private final Log log = LogFactory.getLog(UserController.class);
	
	@RequestMapping(value="/register",method=RequestMethod.GET)
    public String toRegister(Map<String, Object> map) { 
        return "register";
    }
	
	@RequestMapping(value="/register",method=RequestMethod.POST)
    public ModelAndView register(@ModelAttribute("user") User user, BindingResult result,HttpSession session, ModelAndView mav) { 
		if(result.getErrorCount()>0){
			mav.setViewName("register");
			mav.addObject("user",user);
			mav.addObject("error", "注册失败");
			
			return mav;
		}

		if(userService.isNameExist(user.getName())){
			mav.setViewName("register");
			mav.addObject("user",user);
			mav.addObject("error", "用户名已经存在");
			return mav;
		}
		
		if(userService.isEmailExist(user.getEmail())){
			mav.setViewName("register");
			mav.addObject("user",user);
			mav.addObject("error", "该邮箱已经被注册");	
			return mav;
		}
		
		userService.registerUser(user);
		userService.addUserTag("初来乍到", user.getId());
		session.setAttribute("user", user);
		session.setAttribute("isLogin", true);
		mav.setViewName("redirect:/user/info.html");
		return mav;
	}

	@RequestMapping(value = "/login", method = RequestMethod.GET)
	public ModelAndView toLogin(HttpServletRequest request, HttpServletResponse response,
			HttpSession session, ModelAndView mav) {
		mav.setViewName("login");
		mav.addObject("redirect", request.getParameter("redirect"));
		mav.addObject("errormsg", "");
		return mav;
	}

	@RequestMapping(value = "/minilogin", method = RequestMethod.GET)
	public ModelAndView toMiniLogin(HttpServletRequest request, HttpServletResponse response,
			HttpSession session, ModelAndView mav) {
		mav.setViewName("frame/login");
		mav.addObject("redirect", request.getParameter("redirect"));
		mav.addObject("errormsg", "");
		return mav;
	}

	@RequestMapping(value = "/logout", method = RequestMethod.GET)
	public ModelAndView logout(HttpServletRequest request, HttpServletResponse response,
			HttpSession session, ModelAndView mav) {
		session.setAttribute("isLogin", false);
		session.removeAttribute("user");
		session.invalidate();
		mav.setViewName("login");
		mav.addObject("errormsg", "");
		return mav;
	}

	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public ModelAndView login(HttpServletRequest request, HttpServletResponse response,
			ModelAndView mav, HttpSession session) throws UnsupportedEncodingException {

		String nameOrEmail = request.getParameter("name");
		String password = request.getParameter("password");
		String remember = request.getParameter("remember");
		String minilogin = request.getParameter("minilogin");

		User user = userService.login(nameOrEmail, password);
		
		
		if (null == user) {
			if("1".equals(minilogin)){
				mav.setViewName("redirect:/user/minilogin.html");
				mav.addObject("errormsg", "用户名或密码出错");
				mav.addObject("redirect", request.getParameter("redirect"));
				return mav;
			}else{
				mav.setViewName("redirect:/user/login.html");
				mav.addObject("errormsg", "用户名或密码出错");
				mav.addObject("redirect", request.getParameter("redirect"));
				return mav;
			}
			
		}
		else {
			session.setAttribute("user", user);
			session.setAttribute("isLogin", true);
		}
		if (null != remember && "on".equals(remember)) {
			response.addCookie(new Cookie("name", nameOrEmail));
			response.addCookie(new Cookie("password", password));
		}

		if (null != request.getParameter("redirect")
				&& !"".equals(request.getParameter("redirect").trim())) {
			mav.setViewName("redirect:" + request.getParameter("redirect"));
		}
		else {
			if("1".equals(minilogin)){
				mav.setViewName("frame/loginSuccess");
			}else{
				mav.setViewName("redirect:/index.html");
			}
			
		}
		return mav;
	}

	@RequestMapping(value = "/info", method = RequestMethod.GET)
	public String info() {
		return "info";
	}

	@RequestMapping(value = "/infosave", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> infoSave(@RequestBody Map map, HttpSession session)
			throws ParseException {
		Map<String, Object> result = new HashMap<String, Object>();

		String genderStr = (String) map.get("gender");
		int gender = Integer.parseInt(genderStr.trim());
		String privateUrl = (String) map.get("privateUrl");
		String profession = (String) map.get("profession");
		String qq = (String) map.get("qq");
		String birthday = (String) map.get("birthday");

		
		
		User user = (User) session.getAttribute("user");
		if(!"".equals(privateUrl) && userService.isPrivateUrlExist(privateUrl,user.getId())){
			result.put("ok", false);
			result.put("msg", "urlexist");
			result.put("data", profession);
			return result;
		}
		
		user.setProfession(profession);
		if(!birthday.equals("")){
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			Date date = sdf.parse(birthday);
			user.setBirthday(date);
		}
		user.setPrivateUrl(privateUrl);
		user.setGender(gender);
		user.setQq(qq);
		userService.updateUser(user);
		session.setAttribute("user", user);
		result.put("ok", true);
		result.put("msg", "");

		return result;
	}

	@RequestMapping(value = "/checkname", method = RequestMethod.GET)
	@ResponseBody
	public Map<String, Object> checkName(@RequestParam("name") String name) {
		Map<String, Object> result = new HashMap<String, Object>();
		if ("".equals(name) || null == name) {
			result.put("ok", false);
			result.put("msg", "用户名不能为空");
		}
		else if (userService.isNameExist(name)) {
			result.put("ok", false);
			result.put("msg", "该用户已经注册");
		}
		else {
			result.put("ok", true);
			result.put("msg", "");
		}
		return result;
	}

	@RequestMapping(value = "/checkemail", method = RequestMethod.GET)
	@ResponseBody
	public Map<String, Object> checkEmail(@RequestParam("email") String email) {
		Map<String, Object> result = new HashMap<String, Object>();
		if ("".equals(email) || null == email) {
			result.put("ok", false);
			result.put("msg", "Email不能为空");
		}
		else if (userService.isEmailExist(email)) {
			result.put("ok", false);
			result.put("msg", "该Email已经注册");
		}
		else {
			result.put("ok", true);
			result.put("msg", "");
		}
		return result;
	}

	@RequestMapping(value = "/head", method = RequestMethod.GET)
	public String uploadHead(HttpServletRequest request, HttpServletResponse response,
			ModelAndView mav, HttpSession session) {
		return "head";

	}

	@RequestMapping(value = "/uploadHead", method = RequestMethod.POST)
	public ModelAndView getUploadFile(HttpServletRequest request, HttpServletResponse response,
			HttpSession session, ModelAndView mav) {
		String myappPath = request.getSession().getServletContext().getRealPath("/");
		try {
			if (request instanceof MultipartHttpServletRequest) {
				MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;

				// String myappPath = multipartRequest.getServletContext().getRealPath("/");   
				// does not work, oh my god!!  
				MultipartFile file = multipartRequest.getFiles("headImg").get(0);
				long size = file.getSize();
				if (size > 1 * 1024 * 1024) {
					mav.setViewName("head");
					mav.addObject("errormsg", "文件大小请不要超过1M");
					return mav;
				}
				InputStream input = file.getInputStream();
				//input.read(data);
				Image img = ImageIO.read(input);
				int width = img.getWidth(null);
				int height = img.getHeight(null);
				if (width < 200 || height < 200) {
					mav.setViewName("head");
					mav.addObject("errormsg", "图片太小了，请重新上传");
					return mav;
				}
				// create file, if no app context path, will throws access denied.  
				// seems like you could not create any file at tomcat/bin directory!!!  
				//com.mysql.jdbc.PacketTooBigException: Packet for query is too large (3161024 > 1048576). You can change this value on the server by setting the max_allowed_packet' variable.
				long now = System.currentTimeMillis();

				String filePathF = "/upload/tmp/" + now;
				BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
				Graphics g = bi.getGraphics();
				g.drawImage(img, 0, 0, null);
				input.close();

				HeadImage tmpimg = new HeadImage();
				tmpimg.setPath(filePathF);
				tmpimg.setCreateAt(new Date());
				tmpimg.setFormat(ImageUtils.getExtention(file.getOriginalFilename()));
				tmpimg.setSize(file.getSize());
				tmpimg.setHeight(height);
				tmpimg.setWidth(width);
				tmpimg.setImage(file.getBytes());
				imageStoreService.saveHeadImage(tmpimg);
				
				
				mav.addObject("filePath", filePathF+"."+tmpimg.getFormat());
				mav.addObject("width", width);
				mav.addObject("height", height);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}

		mav.setViewName("cuthead");
		return mav;
	}

	@RequestMapping(value = "/cuthead", method = RequestMethod.POST)
	public ModelAndView cutHead(HttpServletRequest request, HttpServletResponse response,
			HttpSession session, ModelAndView mav) {
		String x1 = request.getParameter("x1");
		String y1 = request.getParameter("y1");
		String x2 = request.getParameter("x2");
		String y2 = request.getParameter("y2");
		String w = request.getParameter("w");
		String h = request.getParameter("h");
		String filePath = request.getParameter("filePath");
		String realpath = filePath.substring(0,filePath.lastIndexOf("."));
//		String myappPath = request.getSession().getServletContext().getRealPath("/");
//		String realPath = myappPath + File.separator + filePath;
		User user = (User) session.getAttribute("user");
		try {
			HeadImage headImg = imageStoreService.readHeadImage(realpath);
			ByteArrayInputStream in = new ByteArrayInputStream(headImg.getImage());
			Image img = ImageIO.read(in);
			BufferedImage bi = new BufferedImage(img.getWidth(null), img.getHeight(null),
					BufferedImage.TYPE_INT_RGB);
			Graphics g = bi.getGraphics();
			g.drawImage(img.getScaledInstance(img.getWidth(null), img.getHeight(null),
					Image.SCALE_SMOOTH), 0, 0, null);

			String storePath = "/upload/head/"+user.getId();
//			String path_160 = myappPath + File.separator + "head" + File.separator + "xl"
//					+ File.separator + user.getId() + ".jpg";
//			String path_80 = myappPath + File.separator + "head" + File.separator + "l"
//					+ File.separator + user.getId() + ".jpg";
//			String path_50 = myappPath + File.separator + "head" + File.separator + "m"
//					+ File.separator + user.getId() + ".jpg";
//			String path_24 = myappPath + File.separator + "head" + File.separator + "s"
//					+ File.separator + user.getId() + ".jpg";

			BufferedImage rect = ImageUtils.cropPart(bi, Integer.parseInt(x1),
					Integer.parseInt(y1), Integer.parseInt(w), Integer.parseInt(h));
			
			ResampleOp resampleOp160 = new ResampleOp(160, 160);
			resampleOp160.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Normal);
			BufferedImage img160 = resampleOp160.filter(rect, null);
			
			ByteArrayOutputStream out = new ByteArrayOutputStream();
	        ImageIO.write(img160, "JPEG", out);
	        byte[] b = out.toByteArray();
	        HeadImage headimg = new HeadImage();
	        headimg.setCreateAt(new Date());
	        headimg.setFormat("jpg");
	        headimg.setHeight(160);
	        headimg.setWidth(160);
	        headimg.setSize(b.length);
	        headimg.setPath(storePath);
	        headimg.setImage(b);
	        imageStoreService.saveHeadImage(headimg);
	        imageStoreService.deleteHeadImage(realpath);
			//         rect = ImageUtils.scale2(rect, 160, 160, true);
			//         ImageUtils.saveImg(img160, path_160);
//			ImageIO.write(img160, "JPEG", new File(path_160));

//			ResampleOp resampleOp80 = new ResampleOp(80, 80);
//			resampleOp80.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Normal);
//			BufferedImage img80 = resampleOp80.filter(rect, null);
//			//          ImageUtils.saveImg(img80, path_80);
//			//          rect = ImageUtils.scale2(rect, 80, 80, true);
//			ImageIO.write(img80, "JPEG", new File(path_80));
//
//			ResampleOp resampleOp50 = new ResampleOp(50, 50);
//			resampleOp50.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Normal);
//			BufferedImage img50 = resampleOp50.filter(rect, null);
//			//         ImageUtils.saveImg(img50, path_50);
//			ImageIO.write(img50, "JPEG", new File(path_50));
//
//			ResampleOp resampleOp24 = new ResampleOp(24, 24);
//			resampleOp24.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Normal);
//			BufferedImage img24 = resampleOp24.filter(rect, null);
//			//         ImageUtils.saveImg(img24, path_24);
//			ImageIO.write(img24, "JPEG", new File(path_24));

			user.setHeadImg(user.getId() + ".jpg");
			userService.updateUser(user);
			user.setHeadImg(user.getId() + ".jpg");// + "?t=" + System.currentTimeMillis()
			session.setAttribute("user", user);
		}
		catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		mav.setViewName("head");
		return mav;
	}

	@RequestMapping(value = "/cuthead", method = RequestMethod.GET)
	public ModelAndView toCutHead(HttpServletRequest request, HttpServletResponse response,
			HttpSession session, ModelAndView mav) {
		mav.addObject("width", 1024);
		mav.addObject("height", 724);
		mav.addObject("filePath", "tmp/1377342998664.jpg");
		mav.setViewName("cuthead");
		return mav;
	}

	@RequestMapping(value = "/profilesave", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> saveProfile(@RequestBody Map map, HttpSession session) {
		Map<String, Object> result = new HashMap<String, Object>();
		User user = (User) session.getAttribute("user");
		String profile = (String) map.get("profile");
		user.setProfile(profile);
		userService.updateUser(user);
		session.setAttribute("user", user);
		result.put("ok", true);
		result.put("msg", "");
		return result;
	}

	@RequestMapping(value = "/addtag", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> addTag(@RequestBody Map map, HttpSession session) {
		Map<String, Object> result = new HashMap<String, Object>();

		String tagName = (String) map.get("tagName");
		log.debug(">>>>>>>>>>>>>>>>>>tagName:"+tagName);
		int userId = Integer.parseInt((String) map.get("userId"));
		Tag tag = userService.addUserTag(tagName, userId);
		result.put("ok", true);
		Tag tagnew = new Tag();
		tagnew.setId(tag.getId());
		result.put("data", tagnew);
		return result;
	}

	@RequestMapping(value = "/doAction", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> userAction(@RequestBody Map map, HttpSession session) {
		Map<String, Object> result = new HashMap<String, Object>();
		User user = (User) session.getAttribute("user");
		if (user == null) {
			result.put("ok", false);
			result.put("msg", "请先登录");
			return result;
		}
		int userId = user.getId();
		String type = (String) map.get("type");
		String action = (String) map.get("action");
		int targetId = (Integer) map.get("targetId");
		String resultStr = userService.addUserAction(type, action, targetId, userId);
		result.put("ok", true);
		result.put("msg", resultStr);
		return result;
    }
    
    @RequestMapping(value = "/doCommentAction", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> userCommentAction(@RequestBody Map map, HttpSession session){
		Map<String, Object> result = new HashMap<String, Object>();

		String type = (String) map.get("type");
		String action = (String) map.get("action");
		int targetId = (Integer) map.get("targetId");
		if(type.equals("article")){
			articleService.doCommentAction(targetId,action);
		}else if(type.equals("question")){
			questionService.doCommentAction(targetId,action);
		}
		result.put("ok", true);
		result.put("msg", "success");
		return result;
    }
    
    @RequestMapping(value = "/remove-attension", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> attendsion(@RequestBody Map map, HttpSession session) {
		Map<String, Object> result = new HashMap<String, Object>();
		User user = (User) session.getAttribute("user");
		int userId = user.getId();
		int myId = (Integer) map.get("myid");
		int targetId = (Integer) map.get("targetid");
		if (myId != userId) {
			result.put("ok", false);
			result.put("msg", "请先登录");
		}
		else {
			String str = userService.removeAttention(userId, targetId);
			if (str.equals("success")) {
				user.setFollowNum(user.getFollowNum() - 1);
				result.put("ok", true);
				result.put("msg", "");
			}
			else {
				result.put("ok", false);
				result.put("msg", str);
			}
		}
		return result;
	}

	@RequestMapping(value = "/add-attension", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> addAttendsion(@RequestBody Map map, HttpSession session) {
		Map<String, Object> result = new HashMap<String, Object>();
		User user = (User) session.getAttribute("user");
		int userId = user.getId();
		int myId = (Integer) map.get("myid");
		int targetId = (Integer) map.get("targetid");
		if (myId != userId) {
			result.put("ok", false);
			result.put("msg", "请先登录");
		}
		else {
			String str = userService.addAttention(userId, targetId);
			if (str.equals("success")) {
				user.setFollowNum(user.getFollowNum() + 1);
				result.put("ok", true);
				result.put("msg", "");
			}
			else {
				result.put("ok", false);
				result.put("msg", str);
			}
		}
		return result;
	}
	
	@RequestMapping(value = "/remove-tag", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> removeTag(@RequestBody Map map, HttpSession session) {
		Map<String, Object> result = new HashMap<String, Object>();
		User user = (User) session.getAttribute("user");
		
		if (user == null) {
			result.put("ok", false);
			result.put("msg", "请先登录");
		}
		else {
			int userId = user.getId();
			int tagId = Integer.parseInt((String) map.get("id"));
			userService.removeUserTag(tagId, userId);
			result.put("ok", true);
			result.put("msg", "");
		}
		return result;
	}

}
